home *** CD-ROM | disk | FTP | other *** search
- /*-----------------------------------------------------------------
- Copyright ©1994 Steve Israelson
-
- This file contains the code for the "levelView" class.
- This class handles the displaying of a level in a view.
- -----------------------------------------------------------------*/
-
- #include "levelView.h"
- #include "commandNumbers.h"
- #include "myApplication.h"
- #include "levelUtils.h"
-
-
- /*-----------------------------------------------------------------
- Make a new levelView. Called from the URegistrar.
- -----------------------------------------------------------------*/
- levelView *levelView::CreateViewStream(LStream *inStream)
- {
- return (new levelView(inStream));
- }
-
- /*-----------------------------------------------------------------
- Initialize the view to a known state.
- -----------------------------------------------------------------*/
- levelView::levelView(LStream *inStream) : LView(inStream)
- {
- theLevelData = nil;
- scaleFactor = 63;
- showGrid = false;
- showPoints = true;
- showLines = true;
- showObjects = false;
-
- Point where = {0x7fff, 0x7fff};
- setScale(64, where);
-
- if (!IsTarget())
- SwitchTarget(this);
- }
-
- /*-----------------------------------------------------------------
- Initialize the view to a known state.
- -----------------------------------------------------------------*/
- levelView::levelView(const SPaneInfo &inPaneInfo, const SViewInfo &inViewInfo) : LView(inPaneInfo, inViewInfo)
- {
- theLevelData = nil;
- scaleFactor = 63;
- showGrid = false;
- showPoints = true;
- showLines = true;
- showObjects = false;
-
- Point where = {0x7fff, 0x7fff};
- setScale(64, where);
-
- if (!IsTarget())
- SwitchTarget(this);
- }
-
- /*-----------------------------------------------------------------
- Clean up when we are disposed.
- -----------------------------------------------------------------*/
- levelView::~levelView()
- {
- }
-
- /*-----------------------------------------------------------------
- After the window is created, lets do some stuff.
- -----------------------------------------------------------------*/
- void levelView::FinishCreate()
- {
- fixImageSize();
- LView::FinishCreate();
- Refresh();
- }
-
- /*-----------------------------------------------------------------
- This is so that the scroll bars will work properly.
- They use the image size to decide if scrolling is possible.
- The image is the area that our entire level will take up.
- When this view is put into a ScrollView, the ScrollView will
- set up the scroll bars so we can view all of the image, even
- if it doesn't fit in the window all at once.
- -----------------------------------------------------------------*/
- void levelView::fixImageSize(void)
- {
- long width = offset + 32768L / scaleFactor;
- long height = offset + 32768L / scaleFactor;
- ResizeImageTo(width, height, false);
- }
-
- /*-----------------------------------------------------------------
- Zoom centered on the point where, unless where = 0x7fff, 0x7fff
- There has to be an easier way to do this!
- -----------------------------------------------------------------*/
- void levelView::setScale(long newScale, Point where)
- {
- Rect frame;
- long centerX, centerY, newCenterX, newCenterY;
- long oldScale = scaleFactor;
-
- if (newScale < 4)
- newScale = 4;
- if (newScale > 1024)
- newScale = 1024;
-
- offset = 0x8000L / scaleFactor;
-
- FocusDraw();
- CalcLocalFrameRect(frame);
- // calc center in mara coords
- if (where.h == 0x7fff && where.v == 0x7fff)
- {
- centerX = (frame.left + frame.right) / 2 * scaleFactor;
- centerY = (frame.top + frame.bottom) / 2 * scaleFactor;
- }
- else
- {
- centerX = where.h * scaleFactor;
- centerY = where.v * scaleFactor;
- }
-
- scaleFactor = newScale;
- offset = 0x8000L / scaleFactor;
-
- fixImageSize();
-
- // fix up how big the window can be.
- // if we zoom way out, we dont want the window to be bigger than us.
- SDimension16 newSize = {65535L / scaleFactor, 65535L / scaleFactor};
- LWindow *owner = LWindow::FetchWindowObject(GetMacPort());
- if (owner && owner->IsVisible())
- {
- Rect theRect = (*((WindowPeek)GetMacPort())->contRgn)->rgnBBox;
-
- owner->SetStandardSize(newSize);
-
- if (theRect.right - theRect.left > newSize.width + 15)
- theRect.right = theRect.left + newSize.width + 15;
- if (theRect.bottom - theRect.top > newSize.height + 15)
- theRect.bottom = theRect.top + newSize.height + 15;
- owner->DoSetBounds(theRect);
-
- owner->GetMinMaxSize(theRect);
- theRect.right = newSize.width + 15;
- theRect.bottom = newSize.height + 15;
- owner->SetMinMaxSize(theRect);
- }
-
- SDimension32 theImageSize;
- GetImageSize(theImageSize);
-
- CalcLocalFrameRect(frame);
- // calc width in marathon coords
- newCenterX = (frame.right - frame.left) / 2 * scaleFactor;
- newCenterY = (frame.bottom - frame.top) / 2 * scaleFactor;
-
- // scroll to the center point
-
- long newXpos = (centerX - newCenterX) / scaleFactor;
- long newYpos = (centerY - newCenterY) / scaleFactor;
- if (newXpos < 0)
- newXpos = 0;
- if (newYpos < 0)
- newYpos = 0;
- if (newXpos + (frame.right - frame.left) > theImageSize.width)
- newXpos = theImageSize.width - (frame.right - frame.left);
- if (newYpos + (frame.bottom - frame.top) > theImageSize.height)
- newYpos = theImageSize.height - (frame.bottom - frame.top);
- ScrollImageTo(newXpos, newYpos, false);
-
- Refresh();
- }
-
- /*-----------------------------------------------------------------
- Some one will eventually give us a level to display.
- There may be a better way to handle this, but this method
- allows us to make one view that can display different
- levels in it, just by calling this when a new level
- needs to be displayed.
- -----------------------------------------------------------------*/
- void levelView::setLevelData(levelData *newLevelData)
- {
- theLevelData = newLevelData;
-
- Point mapCenter;
- long centerX, centerY;
- getMapCenter(theLevelData, ¢erX, ¢erY);
- mapCenter.h = offset + centerX / scaleFactor;
- mapCenter.v = offset + centerY / scaleFactor;
- setScale(scaleFactor, mapCenter);
- }
-
- /*-----------------------------------------------------------------
- Handle a mouse click. This is where you can do different
- things, depending on what tool the user has selected.
- -----------------------------------------------------------------*/
- void levelView::ClickSelf(const SMouseDownEvent &inMouseDown)
- {
- FocusDraw();
- if (!IsTarget())
- {
- SwitchTarget(this);
- }
- // short tool = theApp->theToolPalette->curTool;
- Boolean shiftState = (inMouseDown.macEvent.modifiers & shiftKey) ? true: false;
-
- // switch (tool)
- // {
- // case tool_arrow:
- // write code for handling clicks with the arrow tool...
-
- }
-
- /*-----------------------------------------------------------------
- Find out if menu commands are allowed. This is called when
- the user clicks in the menu bar.
- -----------------------------------------------------------------*/
- void levelView::FindCommandStatus(
- CommandT inCommand,
- Boolean &outEnabled,
- Boolean &outUsesMark,
- Char16 &outMark,
- Str255 outName)
- {
- outUsesMark = false;
-
- switch (inCommand)
- {
- case cmd_toggleGrid:
- outUsesMark = true;
- if (showGrid)
- outMark = ''; /* check mark */
- else
- outMark = ' ';
- outEnabled = true;
- break;
- case cmd_togglePoints:
- outUsesMark = true;
- if (showPoints)
- outMark = ''; /* check mark */
- else
- outMark = ' ';
- outEnabled = true;
- break;
- case cmd_toggleLines:
- outUsesMark = true;
- if (showLines)
- outMark = ''; /* check mark */
- else
- outMark = ' ';
- outEnabled = true;
- break;
- case cmd_toggleObjects:
- outUsesMark = true;
- if (showObjects)
- outMark = ''; /* check mark */
- else
- outMark = ' ';
- outEnabled = true;
- break;
- case cmd_zoomIn:
- case cmd_zoomOut:
- outEnabled = true;
- break;
- case cmd_Nothing:
- default:
- LCommander::FindCommandStatus(inCommand, outEnabled, outUsesMark,
- outMark, outName);
- break;
- }
- }
-
- /*-----------------------------------------------------------------
- Do a menu command. This is called after the user selects
- a command from the menu.
- -----------------------------------------------------------------*/
- Boolean levelView::ObeyCommand(CommandT inCommand, void *ioParam)
- {
- Boolean cmdHandled = true;
-
- switch (inCommand)
- {
- case cmd_togglePoints:
- showPoints = !showPoints;
- Refresh();
- break;
- case cmd_toggleLines:
- showLines = !showLines;
- Refresh();
- break;
- case cmd_toggleObjects:
- showObjects = !showObjects;
- Refresh();
- break;
- case cmd_toggleGrid:
- showGrid = !showGrid;
- Refresh();
- break;
- case cmd_zoomIn:
- Point where1 = {0x7fff, 0x7fff};
- setScale(scaleFactor - 8, where1);
- break;
- case cmd_zoomOut:
- Point where2 = {0x7fff, 0x7fff};
- setScale(scaleFactor + 8, where2);
- break;
- case cmd_Nothing:
- default:
- return LCommander::ObeyCommand(inCommand, ioParam);
- break;
- }
- return cmdHandled;
- }
-
- /*-----------------------------------------------------------------
- Draw this view. This gets called by PowerPlant when it needs
- part or all of the view re-drawn.
- -----------------------------------------------------------------*/
- void levelView::DrawSelf()
- {
- Rect frame;
- RGBColor greyColor = {10000, 10000, 10000};
-
- CalcLocalFrameRect(frame);
-
- RGBForeColor(&greyColor);
- PaintRect(&frame);
- ForeColor(blackColor);
-
- drawPolygons();
- if (showGrid)
- drawGrid();
- if (showLines)
- drawLines();
- if (showPoints)
- drawPoints();
- if (showObjects)
- drawObjects();
- PenNormal();
- }
-
- /*-----------------------------------------------------------------
- Draw a grid. Nothing fancy.
- -----------------------------------------------------------------*/
- void levelView::drawGrid(void)
- {
- long scaledX = 0, maxX, x;
- Rect frame;
-
- ForeColor(redColor);
- PenPat(&qd.gray);
- CalcLocalFrameRect(frame);
- if (frame.right > frame.bottom)
- maxX = frame.right;
- else
- maxX = frame.bottom;
- for (x = 0; scaledX < maxX; x += 4096)
- {
- scaledX = x / scaleFactor;
- MoveTo(scaledX, 0);
- LineTo(scaledX, 32000);
- }
- for (x = 0, scaledX = 0; scaledX < maxX; x += 4096)
- {
- scaledX = x / scaleFactor;
- MoveTo(0, scaledX);
- LineTo(32000, scaledX);
- }
- PenNormal();
- }
-
- /*-----------------------------------------------------------------
- Draw all the objects.
- -----------------------------------------------------------------*/
- void levelView::drawObjects(void)
- {
- for (int x = 0; x < theLevelData->numObjects; ++x)
- drawObject(x);
- }
-
- /*-----------------------------------------------------------------
- Draw one object.
- -----------------------------------------------------------------*/
- void levelView::drawObject(short x)
- {
- RGBColor objectColor = {65535, 0, 0};
- Rect theRect;
-
- theRect.left = offset + theLevelData->theObjects[x].x / scaleFactor - 4;
- theRect.top = offset + theLevelData->theObjects[x].y / scaleFactor - 4;
- theRect.right = theRect.left + 4 * 2;
- theRect.bottom = theRect.top + 4 * 2;
-
- short angle = (theLevelData->theObjects[x].facing * 360L) / 512L + 20 + 90;
-
- InsetRect(&theRect, -1, -1);
- ForeColor(blackColor);
- PaintOval(&theRect);
- InsetRect(&theRect, 1, 1);
-
- switch (theLevelData->theObjects[x].type)
- {
- case object_monster:
- objectColor.red = 65535;
- objectColor.green = 0;
- objectColor.blue = 0;
- RGBForeColor(&objectColor);
- break;
- case object_scenery:
- objectColor.red = 65535;
- objectColor.green = 65535;
- objectColor.blue = 65535;
- RGBForeColor(&objectColor);
- break;
- case object_weapon:
- objectColor.red = 0;
- objectColor.green = 65535;
- objectColor.blue = 0;
- RGBForeColor(&objectColor);
- break;
- case object_player:
- objectColor.red = 0;
- objectColor.green = 0;
- objectColor.blue = 65535;
- RGBForeColor(&objectColor);
- break;
- case object_goal:
- objectColor.red = 65535;
- objectColor.green = 65535;
- objectColor.blue = 0;
- RGBForeColor(&objectColor);
- break;
- }
- PaintArc(&theRect, angle, 320);
- }
-
- /*-----------------------------------------------------------------
- Draw the lines. Draws light lines when there is no wall.
- -----------------------------------------------------------------*/
- void levelView::drawLines(void)
- {
- RGBColor greenColor = {0, 65535, 0};
- RGBColor greyColor = {40000, 40000, 40000};
- short lineSize = 1;
-
- for (int x = 0; x < theLevelData->numLines; ++x)
- {
- LINSdata *theLine = &theLevelData->theLines[x];
- if (theLine->leftPoly != -1 && theLine->rightPoly != -1)
- {
- // if the floors are the same height, then there is no wall
- if (theLevelData->thePolys[theLine->leftPoly].floorHeight ==
- theLevelData->thePolys[theLine->rightPoly].floorHeight)
- {
- PenSize(lineSize, lineSize);
- RGBForeColor(&greyColor);
- }
- else
- {
- PenNormal();
- PenSize(lineSize, lineSize);
- RGBForeColor(&greenColor);
- }
- }
- else
- { // if there is no polygon on one side, the there must be a wall
- PenNormal();
- PenSize(lineSize ,lineSize);
- RGBForeColor(&greenColor);
- }
- // actually draw the line now that its color has been determined
- PNTSdata *pointA, *pointB;
- pointA = &theLevelData->thePoints[theLine->pointA];
- pointB = &theLevelData->thePoints[theLine->pointB];
- MoveTo(offset + pointA->x / scaleFactor, offset + pointA->y / scaleFactor);
- LineTo(offset + pointB->x / scaleFactor, offset + pointB->y / scaleFactor);
- }
- ForeColor(blackColor);
- PenNormal();
- }
-
- /*-----------------------------------------------------------------
- Draw some cool points. Make a circle with a thin black line
- around it.
- -----------------------------------------------------------------*/
- void levelView::drawPoints(void)
- {
- short x;
- Rect theRect;
- RGBColor greenColor = {0, 65535, 0};
- short pointSize = 2;
-
- PenNormal();
-
- for (x = 0; x < theLevelData->numPoints; ++x)
- {
- PNTSdata *thePoint;
-
- thePoint = &theLevelData->thePoints[x];
-
- theRect.left = offset + thePoint->x / scaleFactor - pointSize;
- theRect.top = offset + thePoint->y / scaleFactor - pointSize;
- theRect.right = theRect.left + (pointSize << 1);
- theRect.bottom = theRect.top + (pointSize << 1);
-
- ForeColor(blackColor);
- InsetRect(&theRect, -1, -1);
- PaintOval(&theRect);
- RGBForeColor(&greenColor);
- InsetRect(&theRect, 1, 1);
- PaintOval(&theRect);
- }
- }
-
- /*-----------------------------------------------------------------
- Make and draw a polygon.
- -----------------------------------------------------------------*/
- void levelView::drawPolygons(void)
- {
- RGBColor liteColor = {0, 0, 65535};
- PolyHandle thePolyHandle;
-
- RGBForeColor(&liteColor); // default color
- for (int x = 0; x < theLevelData->numPolys; ++x)
- {
- thePolyHandle = makePolyPolygon(x);
- if (thePolyHandle)
- {
- // paint poly
- PaintPoly(thePolyHandle);
- // dispose poly
- KillPoly(thePolyHandle);
- }
- PenNormal();
- }
- ForeColor(blackColor);
- }
-
- /*-----------------------------------------------------------------
- Make a quickdraw polygon for a poly.
- -----------------------------------------------------------------*/
- PolyHandle levelView::makePolyPolygon(long thePoly)
- {
- if (thePoly == -1 || thePoly >= theLevelData->numPolys)
- return nil;
-
- // open poly here
- PolyHandle thePolyHandle = OpenPoly();
- Boolean first = true;
- short firstX, firstY;
- short *vertexIndex;
- short vertexCount;
-
- vertexIndex = theLevelData->thePolys[thePoly].vertexIndex;
- vertexCount = theLevelData->thePolys[thePoly].vertexCount;
- for (int y = 0; y < vertexCount; ++y)
- {
- PNTSdata *pointA;
-
- pointA = &theLevelData->thePoints[vertexIndex[y]];
- if (first)
- {
- first = false;
- firstX = offset + pointA->x / scaleFactor;
- firstY = offset + pointA->y / scaleFactor;
- MoveTo(firstX, firstY);
- }
- else
- LineTo(offset + pointA->x / scaleFactor, offset + pointA->y / scaleFactor);
- }
- // close poly here
- LineTo(firstX, firstY);
- ClosePoly(); // closes the fisrt and last line as well
- return thePolyHandle;
- }
-
-
-
-
-